﻿using System;
using System.Linq;
using System.Windows.Input;
using NTQOnlineExam.Services.CommandService.TermSection;
using NTQOnlineExam.Services.DBCommand.Section;
using NTQOnlineExam.Services.EntityFW.Context;
using NTQOnlineExam.Services.EntityFW.Entity;
using NTQOnlineExam.Services.Infrastructure;
using NTQOnlineExam.Services.Infrastructure.Utility;

namespace NTQOnlineExam.Services.CommandService
{
    public class SectionCommandService : ISectionCommandService
    {
        private readonly ICommandExecutor _commandExecutor;

        public SectionCommandService(ICommandExecutor commandExecutor)
        {
            _commandExecutor = commandExecutor;
        }

        public bool DeleteSection(int sectionId)
        {
            Guard.Against<ArgumentException>(sectionId <= 0, "Section Id is required.");
            var termId = 0;
            using (var context = new ExamOnlineDbContext())
            {
                Section section = context.Sections.Find(sectionId);
                Guard.Against<ApplicationException>(section == null, string.Format("Can not find any section having Id = '{0}'", sectionId));

                var referencedItems = context.Database.SqlQuery<int>("Select QuestionId FROM dbo.Question WHERE SectionId = " + sectionId).FirstOrDefault<int>();
                Guard.Against<ApplicationException>(referencedItems > 0, string.Format("Can not delete the section having Id = '{0}', it's referenced by some questions", sectionId));
                termId = section.TermId;
                context.Set<Section>().Remove(section);
                context.SaveChanges();
            }
            try
            {
                ReArrangeSectionOrder(termId);
            }
            catch
            {
                
            }
            return true;
        }

        bool ISectionCommandService.Delete(TermSection.DeleteSectionCommand command)
        {
            Guard.ArgumentIsNotNull(command, "command");

            foreach (var id in command.SectionIds)
            {
                DeleteSection(id);
            }
            return true;
        }

        bool ISectionCommandService.Update(TermSection.UpdateSectionCommand command)
        {
            Guard.ArgumentIsNotNull(command, "command");
            Guard.Against<ArgumentException>(command.SectionId <= 0, "Section Id is required");
            Guard.Against<ArgumentException>(command.TermId <= 0, "Term Id is required");
            Guard.Against<ArgumentException>(string.IsNullOrEmpty(command.SectionName), "Section name can not be empty");

            using (var context = new ExamOnlineDbContext())
            {
                Section section = context.Sections.Find(command.SectionId);
                Guard.Against<ApplicationException>(section == null, string.Format("Can not find any section having Id = '{0}'", command.SectionId));
                section.TermId = command.TermId;
                section.Description = command.Description;
                section.SectionName = command.SectionName;
                context.Entry(section).State = System.Data.EntityState.Modified;
                context.SaveChanges();
            }
            return true;
        }

        int ISectionCommandService.Create(TermSection.CreateSectionCommand command)
        {
            Guard.ArgumentIsNotNull(command, "command");
            Guard.Against<ArgumentException>(command.TermId <= 0, "Term Id is required");
            Guard.Against<ArgumentException>(string.IsNullOrEmpty(command.SectionName), "Term name can not be empty");
            var maxOrderOfSection = _commandExecutor.Execute(new GetMaxOrderSectionByTermDbCommand(command.TermId));
            using (var context = new ExamOnlineDbContext())
            {
                Section section = new Section
                {
                    TermId = command.TermId,
                    SectionName = command.SectionName,
                    Description = command.Description,
                    Order = maxOrderOfSection + 1
                };
                context.Set<Section>().Add(section);
                context.SaveChanges();
                return section.SectionId;
            }
        }

        public bool ChangeSectionOrder(ChangeSectionOrder command)
        {
            return _commandExecutor.Execute(new ChangeSectionOrderDbCommand(command.SectionId, command.NewOrder));
        }

        private void ReArrangeSectionOrder(int termId)
        {
            _commandExecutor.Execute(new ReArrangeSectionOrderInTermDbCommand(termId));
        }
    }
}

